Skip to content
65 linesCodeBlameRaw
1import type { APIRoute, GetStaticPaths } from 'astro';
2import { getCollection } from 'astro:content';
3
4import { AGENTS, AGENTS_WITH_TOKEN, type AgentSetup } from '../data/agents';
5import { DIAGRAMS } from '../diagrams';
6import { toMarkdown } from '../diagrams/engine';
7
8/** A diagram, as the text it is drawn from. */
9function diagramMarkdown(name: string): string {
10 const spec = DIAGRAMS[name];
11 if (!spec) throw new Error(`No diagram named "${name}".`);
12 return toMarkdown(spec);
13}
14
15/** The agent toggle, as plain Markdown: each agent's snippet under its name. */
16function agentsMarkdown(agents: AgentSetup[]): string {
17 return agents
18 .map((agent) => {
19 const where = agent.file ? ` (in \`${agent.file}\`)` : '';
20 const then = agent.then ? `\n\n${agent.then}` : '';
21 const fence = '```';
22 return `**${agent.label}**${where}:\n\n${fence}${agent.lang}\n${agent.code}\n${fence}${then}`;
23 })
24 .join('\n\n');
25}
26
27/**
28 * Every page as Markdown, at its path plus `.md`, for "Copy page" and for
29 * agents that read the docs: the title, what it is about, then the page.
30 */
31export const getStaticPaths: GetStaticPaths = async () => {
32 const pages = await getCollection('docs');
33 return pages.map((page) => ({
34 params: { slug: page.id === '' ? 'index' : page.id },
35 props: { page },
36 }));
37};
38
39export const GET: APIRoute = ({ props }) => {
40 const { page } = props as { page: Awaited<ReturnType<typeof getCollection<'docs'>>>[number] };
41 const { title, description } = page.data;
42 // MDX pages keep their markup; strip imports and leave the rest readable.
43 const body = (page.body ?? '')
44 .replace(/^import .*$/gm, '')
45 // Tabs read as each tab's content under its label in bold.
46 .replace(/^[ \t]*<\/?Tabs[^>]*>[ \t]*\n?/gm, '')
47 .replace(/^[ \t]*<\/TabItem>[ \t]*$/gm, '')
48 .replace(/^([ \t]*)<TabItem label="([^"]+)"[^>]*>[ \t]*$/gm, '$1**$2**\n')
49 .replace(/^([ \t]*)<AgentSetup( variant="token")? \/>$/gm, (_match, indent: string, token?: string) =>
50 agentsMarkdown(token ? AGENTS_WITH_TOKEN : AGENTS)
51 .split('\n')
52 .map((line) => (line ? indent + line : line))
53 .join('\n'),
54 )
55 // A diagram reads as its boxes and arrows, or its numbered steps.
56 .replace(/^([ \t]*)<Diagram name="([^"]+)" \/>$/gm, (_match, indent: string, name: string) =>
57 diagramMarkdown(name)
58 .split('\n')
59 .map((line) => (line ? indent + line : line))
60 .join('\n'),
61 )
62 .trim();
63 const text = `# ${title}\n\n${description ? `> ${description}\n\n` : ''}${body}\n`;
64 return new Response(text, { headers: { 'content-type': 'text/markdown; charset=utf-8' } });
65};